//
//  XSRequestDatas.m
//  XSWangLuo
//
//  Created by xingshuai on 2020/11/6.
//

#import "XSRequestDatas.h"

static XSRequestDatas *requests = nil;

@implementation XSRequestDatas

/** 单例 */
+(instancetype)shareRequestDatas {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        requests = [[XSRequestDatas alloc]init];
    });
    return requests;
}

/** 防止外部调用alloc 或者 new */
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        requests = [super allocWithZone:zone];
    });
    return requests;
}

/** 防止外部调用copy */
- (id)copyWithZone:(nullable NSZone *)zone {
    return requests;
}

/** 防止外部调用mutableCopy */
- (id)mutableCopyWithZone:(nullable NSZone *)zone {
    return requests;
}

/// POST 网络请求
/// @param url       请求路径url
/// @param parameter 请求参数
/// @param success   请求成功回调
/// @param failure   请求失败处理
+(void)requestPostWithUrl:(NSString *)url withParameter:(NSMutableDictionary *)parameter success:(void(^)(id response))success failure:(void(^)(NSError *err))failure {
    parameter = [self addCurrencyParams:parameter];
    //NSLog(@"parameter = %@",parameter);
    kWeakSelf(self);
    AFHTTPSessionManager *mgr = [weakself httpManager];
    [mgr POST:url parameters:parameter headers:nil progress:^(NSProgress * _Nonnull uploadProgress) {
        // 进度 uploadProgress
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (success) {
            success(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (error) {
            failure(error);
        }
    }];
}

/// GET 网络请求
/// @param url       请求路径url
/// @param parameter 请求参数
/// @param success   请求成功回调
/// @param failure   请求失败处理
+(void)requestGetWithUrl:(NSString *)url withParameter:(NSMutableDictionary *)parameter success:(void(^)(id response))success failure:(void(^)(NSError *err))failure {
    kWeakSelf(self);
    AFHTTPSessionManager *mgr = [weakself httpManager];
    [mgr GET:url parameters:parameter headers:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        // 进度 downloadProgress
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (success) {
            success(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (error) {
            failure(error);
        }
    }];
}

/// 上传图片多张
/// @param url       请求路径url
/// @param parameter 请求参数
/// @param imgList   要上传的图片数组
/// @param success   请求成功回调
/// @param failure   请求失败处理
+(void)requestUpLoadImageWithUrl:(NSString *)url withParameter:(NSMutableDictionary *)parameter withImgs:(NSArray *)imgList success:(void(^)(id response))success failure:(void(^)(NSError *err))failure {
    kWeakSelf(self);
    AFHTTPSessionManager *mgr = [weakself httpManager];
    [mgr POST:url parameters:parameter headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        // formData: 专门用于拼接需要上传的数据,在此位置生成一个要上传的数据体
        for (int i = 0; i < imgList.count; i ++) {
            UIImage *img = [imgList objectAtIndex:i];
            // 压缩图片
            NSData *imageData = UIImageJPEGRepresentation(img, 1.0);
            if (imageData.length>100*1024)
            {
                if (imageData.length > 1024 * 1024) {//1M以及以上
                    imageData = UIImageJPEGRepresentation(img, 0.1);
                }else if (imageData.length > 512 * 1024) {//0.5M-1M
                    imageData = UIImageJPEGRepresentation(img, 0.5);
                }else if (imageData.length > 200 * 1024) {//0.25M-0.5M
                    imageData = UIImageJPEGRepresentation(img, 0.9);
                }
            }
            // 上传文件时，文件不允许被覆盖/重名
            // 可以在上传时使用当前的系统事件作为文件名
            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
            // 设置时间格式
            [formatter setDateFormat:@"yyyyMMddHHmmss"];
            NSString *dateString = [formatter stringFromDate:[NSDate date]];
            NSString *fileName = [NSString  stringWithFormat:@"%@.jpg", dateString];
            /*
             1. appendPartWithFileData：要上传的照片[二进制流]
             2. name：对应网站上[upload.php中]处理文件的字段（比如upload）
             3. fileName：要保存在服务器上的文件名
             4. mimeType：上传的文件的类型
             */
            [formData appendPartWithFileData:imageData name:@"upload" fileName:fileName mimeType:@"image/jpeg"]; //
        }
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        // 上传进度 uploadProgress
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (success) {  // 上传成功
            success(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (error) {   // 上传失败
            failure(error);
        }
    }];
}

/// 网络下载
/// @param url       请求路径url
/// @param parameter 请求参数
/// @param success   请求成功回调
/// @param failure   请求失败处理
+(void)requestDownLoadWithUrl:(NSString *)url withParameter:(NSMutableDictionary *)parameter success:(void(^)(id response))success failure:(void(^)(NSError *err))failure {
    kWeakSelf(self);
    AFHTTPSessionManager *mgr = [weakself httpManager];
    NSURLRequest *requset = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost/video.mp4"]];
    //返回一个下载任务对象
    NSURLSessionDownloadTask *loadTask = [mgr downloadTaskWithRequest:requset progress:^(NSProgress * _Nonnull downloadProgress) {
        // completedUnitCount 下载的大小
        // totalUnitCount文件的总大小
        NSLog(@"进度 = %f",1.0 *downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        NSString *fullPath =[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject stringByAppendingString:response.suggestedFilename];
        NSLog(@"targetPath-：%@---fullPath:-%@",targetPath,fullPath);
        //这个block 需要返回一个目标 地址 存储下载的文件
        return  [NSURL fileURLWithPath:fullPath];
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        NSLog(@"下载完成地址:%@",filePath);
    }];
    //启动下载任务--开始下载
    [loadTask resume];
}

/// 特殊网络请求 header(请求头参数) + body(对象参数)
/// @param methodType    请求方式（get/post
/// @param url           请求路径url
/// @param headParameter 请求头参数集合
/// @param bodyParameter body参数集合
/// @param success       请求成功
/// @param failure       请求失败
+(void)requestAddBodyWithMethod:(XSRequestMethodType)methodType withUrl:(NSString *)url withHeadParamter:(NSDictionary *)headParameter withBodyParameter:(NSDictionary *)bodyParameter success:(void(^)(id response))success failure:(void(^)(NSError *err))failure {
    // 服务器地址
    NSString *requestUrl = [NSString stringWithFormat:@"%@%@",XS_BASEURL,url];
    // 请求方式
    NSString *strHttp = methodType == XSRequestMethodTypePost ? @"POST" : @"GET";
    // 添加body参数用这个 NSMutableURLRequest
    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:strHttp URLString:requestUrl parameters:nil error:nil];
    // 请求时间
    request.timeoutInterval= 10;
    // 添加请求头参数
    NSArray *keys = [headParameter allKeys];
    NSArray *values = [headParameter allValues];
    for (int i = 0; i < keys.count; i ++) {
        [request setValue:values[i] forHTTPHeaderField:keys[i]];
    }
    
    // 在这里将参数放入到body
    NSData *data = [NSJSONSerialization dataWithJSONObject:bodyParameter options:NSUTF8StringEncoding error:nil];
    [request setHTTPBody:data];
    
    // 下面走网络接口进行数据处理
    kWeakSelf(self);
    AFHTTPSessionManager *mgr = [weakself httpManager];
    [[mgr dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse *response,id responseObject,NSError *error){
        if (responseObject != nil) {
            success(responseObject);
        }
        if (error) {
            failure(error);
        }
    }]resume];
}

// 初始化 AFHTTPSessionManager
+(AFHTTPSessionManager *)httpManager {
    NSURL *myBaseUrl = [NSURL URLWithString:XS_BASEURL];
    /** 创建请求管理管理对象 */
    AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithBaseURL:myBaseUrl];
    // https ssl 验证。
    //[manager setSecurityPolicy:[self customSecurityPolicy]];
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"text/plain",@"application/json", @"text/json", @"text/javascript",@"image/jpeg", nil];
    /** 过滤nsnull参数 */
    ((AFJSONResponseSerializer *)manager.responseSerializer).removesKeysWithNullValues = YES;
    /** 请求数据和接收数据的格式 */
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    manager.requestSerializer  = [AFJSONRequestSerializer  serializer];
    /** 设置请求成功后的接收内容类型 */
    manager.requestSerializer.timeoutInterval = 30;
    
    /** 模拟添加请求头参数
    NSArray *keys = [headList allKeys];
    NSArray *values = [headList allValues];
    for (int i = 0; i < keys.count; i ++)
    {
        [manager.requestSerializer setValue:values[i] forHTTPHeaderField:keys[i]];
    }
     */
    
    return manager;
}

//添加通用参数
+(NSMutableDictionary *)addCurrencyParams:(NSMutableDictionary *)params {
    if (params == nil) {
        params = [NSMutableDictionary dictionary];
    }
    if (![params objectForKey:@"channelid"]) {
        [params setObject:@"199999" forKey:@"channelid"];
    }
    if (![params objectForKey:@"devid"]) {
        [params setObject:@"1899999" forKey:@"devid"];
    }
    if (![params objectForKey:@"osVersion"]) {
        [params setObject:@"13.3" forKey:@"osVersion"];
    }
    if (![params objectForKey:@"platform"]) {
        [params setObject:@"ios" forKey:@"platform"];
    }
    if (![params objectForKey:@"roleId"]) {
        [params setObject:@"33586" forKey:@"roleId"];
    }
    if (![params objectForKey:@"roleType"]) {
        [params setObject:@"3" forKey:@"roleType"];
    }
    if (![params objectForKey:@"time"]) {
        [params setObject:@"20201109095505" forKey:@"time"];
    }
    if (![params objectForKey:@"token"]) {
        [params setObject:@"9d81174eb12053ab4a449f7a762800e1" forKey:@"token"];
    }
    if (![params objectForKey:@"udid"]) {
        [params setObject:@"49B34967-0288-4835-AA45-D044FC8D3AAD" forKey:@"udid"];
    }
    if (![params objectForKey:@"userId"]) {
        [params setObject:@"44" forKey:@"userId"];
    }
    if (![params objectForKey:@"version"]) {
        [params setObject:@"4.1.8.1" forKey:@"version"];
    }
    //生成加密参数
    //NSString *verify = [self verifyParams:params];
    //[params setObject:verify forKey:@"sign"];
    
    return params;
}


// https ssl 验证函数
+(AFSecurityPolicy *)customSecurityPolicy {
    // 先导入证书 证书由服务端生成，具体由服务端人员操作
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"xxx" ofType:@"cer"];//证书的路径
    NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
    // AFSSLPinningModeCertificate 使用证书验证模式
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    // allowInvalidCertificates 是否允许无效证书（也就是自建的证书），默认为NO
    // 如果是需要验证自建证书，需要设置为YES
    securityPolicy.allowInvalidCertificates = YES;
      
    //validatesDomainName 是否需要验证域名，默认为YES;
    //假如证书的域名与你请求的域名不一致，需把该项设置为NO；如设成NO的话，即服务器使用其他可信任机构颁发的证书，也可以建立连接，这个非常危险，建议打开。
    //置为NO，主要用于这种情况：客户端请求的是子域名，而证书上的是另外一个域名。因为SSL证书上的域名是独立的，假如证书上注册的域名是www.google.com，那么mail.google.com是无法验证通过的；当然，有钱可以注册通配符的域名*.google.com，但这个还是比较贵的。
    //如置为NO，建议自己添加对应域名的校验逻辑。
    securityPolicy.validatesDomainName = NO;
    securityPolicy.pinnedCertificates = [[NSSet alloc] initWithObjects:cerData, nil];
      
    return securityPolicy;
}



@end
